package com.ijpay.alipay;

import java.io.IOException;
import java.io.Serializable;
import java.util.Map;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.ijpay.alipay.enums.AliDomain;
import com.sojson.config.exception.TransException;
import com.sojson.util.SystemParamBaseUtil;
import com.sojson.util.cache.CacheUtil;
import com.sojson.util.pay.ali.constant.AliConstant;

import cn.hutool.core.util.StrUtil;

/**
 * <p>IJPay 让支付触手可及，封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
 *
 * <p>不依赖任何第三方 mvc 框架，仅仅作为工具使用简单快速完成支付模块的开发，可轻松嵌入到任何系统里。 </p>
 *
 * <p>IJPay 交流群: 723992875</p>
 *
 * <p>Node.js 版: https://gitee.com/javen205/TNWXX</p>
 *
 * <p>支付宝支付配置</p>
 *
 * @author Javen
 */
public class AliPayApiConfig implements Serializable {
    private static final long serialVersionUID = -4736760736935998953L;

    /** 应用ID */
    private String appId;
    /** 仅支持JSON */
    private String format;
    /** 请求使用的编码格式,如utf-8,gbk,gb2312等 */
    private String charset;
    /** 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 */
    private String signType;
    /** 私钥 */
    private String privateKey;
    /** 公钥 */
    private String aliPayPublicKey;
    /** 应用公钥证书路径 */
    private String appCertPath;
    /** 支付宝公钥证书文件路径 */
    private String aliPayCertPath;
    /** 支付宝根证书路径 */
    private String aliPayRootCertPath;
    /** 接口域名 */
    private String serviceUrl;
    /** 签名是否使用证书 */
    private boolean certModel;
    private AlipayClient alipayClient;

    public AliPayApiConfig() {
        try {
            Map<String, String> config = CacheUtil.CACHE_REDIS.getMap(SystemParamBaseUtil.MAP_KEY);
            setAppId(config.get(AliConstant.DEFAULT_APPID_CACHE_NAME));
            setServiceUrl(AliDomain.CHINA.getType());
            setPrivateKey(config.get(AliConstant.KEY_PRIVATE));
            setAliPayPublicKey(config.get(AliConstant.KEY_PUBLIC));
            setAppCertPath(AliConstant.CA_CERT_FILE_PATH_APP_CERT_PUBLIC);
            setAliPayCertPath(AliConstant.CA_CERT_FILE_PATH_ALIPAY_CERT_PUBLIC_KEY);
            setAliPayRootCertPath(AliConstant.CA_CERT_FILE_PATH_ALIPAY_ROOT_CERT);
            buildByCert();
        } catch (Exception e) {
            throw new TransException(e);
        }
    }

    public static AliPayApiConfig builder() throws IOException {
        return new AliPayApiConfig();
    }

    /**
     * 普通公钥方式
     *
     * @return AliPayApiConfig 支付宝配置
     */
    public AliPayApiConfig build() {
        this.alipayClient = new DefaultAlipayClient(getServiceUrl(), getAppId(), getPrivateKey(), getFormat(),
            getCharset(), getAliPayPublicKey(), getSignType());
        return this;
    }

    /**
     * 证书模式
     *
     * @return AliPayApiConfig 支付宝配置
     * @throws AlipayApiException 支付宝 Api 异常
     */
    public AliPayApiConfig buildByCert() throws AlipayApiException {
        return build(getAppCertPath(), getAliPayCertPath(), getAliPayRootCertPath());
    }

    /**
     * @param appCertPath        应用公钥证书路径
     * @param aliPayCertPath     支付宝公钥证书文件路径
     * @param aliPayRootCertPath 支付宝CA根证书文件路径
     * @return {@link AliPayApiConfig}  支付宝支付配置
     * @throws AlipayApiException 支付宝 Api 异常
     */
    public AliPayApiConfig build(String appCertPath, String aliPayCertPath, String aliPayRootCertPath)
        throws AlipayApiException {
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl(getServiceUrl());
        certAlipayRequest.setAppId(getAppId());
        certAlipayRequest.setPrivateKey(getPrivateKey());
        certAlipayRequest.setFormat(getFormat());
        certAlipayRequest.setCharset(getCharset());
        certAlipayRequest.setSignType(getSignType());
        certAlipayRequest.setCertPath(appCertPath);
        certAlipayRequest.setAlipayPublicCertPath(aliPayCertPath);
        certAlipayRequest.setRootCertPath(aliPayRootCertPath);
        this.alipayClient = new DefaultAlipayClient(certAlipayRequest);
        this.certModel = true;
        return this;
    }

    /** 获取应用ID */
    public String getAppId() {
        if (StrUtil.isEmpty(appId)) {
            throw new IllegalStateException("appId 未被赋值");
        }
        return appId;
    }

    /** 设置应用ID */
    public AliPayApiConfig setAppId(String appId) {
        if (StrUtil.isEmpty(appId)) {
            throw new IllegalArgumentException("appId 值不能为 null");
        }
        this.appId = appId;
        return this;
    }

    /** 获取仅支持JSON */
    public String getFormat() {
        if (StrUtil.isEmpty(format)) {
            format = "json";
        }
        return format;
    }

    /** 获取请求使用的编码格式,如utf-8,gbk,gb2312等 */
    public String getCharset() {
        if (StrUtil.isEmpty(charset)) {
            charset = "UTF-8";
        }
        return charset;
    }

    /** 设置请求使用的编码格式,如utf-8,gbk,gb2312等 */
    public AliPayApiConfig setCharset(String charset) {
        if (StrUtil.isEmpty(charset)) {
            charset = "UTF-8";
        }
        this.charset = charset;
        return this;
    }

    /** 获取商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 */
    public String getSignType() {
        if (StrUtil.isEmpty(signType)) {
            signType = "RSA2";
        }
        return signType;
    }

    /** 设置商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 */
    public AliPayApiConfig setSignType(String signType) {
        if (StrUtil.isEmpty(signType)) {
            signType = "RSA2";
        }
        this.signType = signType;
        return this;
    }

    /** 获取私钥 */
    public String getPrivateKey() {
        if (StrUtil.isBlank(privateKey)) {
            throw new IllegalStateException("privateKey 未被赋值");
        }
        return privateKey;
    }

    /** 设置私钥 */
    public AliPayApiConfig setPrivateKey(String privateKey) {
        if (StrUtil.isEmpty(privateKey)) {
            throw new IllegalArgumentException("privateKey 值不能为 null");
        }
        this.privateKey = privateKey;
        return this;
    }

    /** 获取公钥 */
    public String getAliPayPublicKey() {
        return aliPayPublicKey;
    }

    /** 设置公钥 */
    public AliPayApiConfig setAliPayPublicKey(String aliPayPublicKey) {
        this.aliPayPublicKey = aliPayPublicKey;
        return this;
    }

    /** 获取应用公钥证书路径 */
    public String getAppCertPath() {
        return appCertPath;
    }

    /** 设置应用公钥证书路径 */
    public AliPayApiConfig setAppCertPath(String appCertPath) {
        this.appCertPath = appCertPath;
        return this;
    }

    /** 获取支付宝公钥证书文件路径 */
    public String getAliPayCertPath() {
        return aliPayCertPath;
    }

    /** 设置支付宝公钥证书文件路径 */
    public AliPayApiConfig setAliPayCertPath(String aliPayCertPath) {
        this.aliPayCertPath = aliPayCertPath;
        return this;
    }

    /** 获取支付宝根证书路径 */
    public String getAliPayRootCertPath() {
        return aliPayRootCertPath;
    }

    /** 设置支付宝根证书路径 */
    public AliPayApiConfig setAliPayRootCertPath(String aliPayRootCertPath) {
        this.aliPayRootCertPath = aliPayRootCertPath;
        return this;
    }

    /** 获取接口域名 */
    public String getServiceUrl() {
        if (StrUtil.isEmpty(serviceUrl)) {
            throw new IllegalStateException("serviceUrl 未被赋值");
        }
        return serviceUrl;
    }

    /** 设置接口域名 */
    public AliPayApiConfig setServiceUrl(String serviceUrl) {
        if (StrUtil.isEmpty(serviceUrl)) {
            serviceUrl = "https://openapi.alipay.com/gateway.do";
        }
        this.serviceUrl = serviceUrl;
        return this;
    }

    /** 获取签名是否使用证书 */
    public boolean getCertModel() {
        return certModel;
    }

    /** 设置签名是否使用证书 */
    public AliPayApiConfig setCertModel(boolean certModel) {
        this.certModel = certModel;
        return this;
    }

    public AlipayClient getAliPayClient() {
        if (alipayClient == null) {
            throw new IllegalStateException("aliPayClient 未被初始化");
        }
        return alipayClient;
    }

}